package com.wt.admin.service.chart.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import com.aizuda.easy.security.code.BasicCode;
import com.wt.admin.domain.dto.chat.ChatDTO;
import com.wt.admin.domain.dto.chat.ChatModelContentDTO;
import com.wt.admin.domain.dto.chat.ChatModelDTO;
import com.wt.admin.domain.entity.chat.ChatModelContentEntity;
import com.wt.admin.domain.entity.chat.ChatModelEntity;
import com.wt.admin.domain.entity.chat.ChatModelFileEntity;
import com.wt.admin.domain.vo.chart.ChatModeListVO;
import com.wt.admin.domain.vo.chart.ChatModelContentVO;
import com.wt.admin.domain.vo.chart.ChatModelFileVO;
import com.wt.admin.domain.vo.chart.ChatModelVO;
import com.wt.admin.domain.vo.language.ClassificationVO;
import com.wt.admin.domain.vo.sys.UserVO;
import com.wt.admin.service.chart.ChatModelContentService;
import com.wt.admin.service.chart.ChatModelFileService;
import com.wt.admin.service.chart.ChatModelService;
import com.wt.admin.service.chart.ChatProxyService;
import com.wt.admin.service.file.UploadFileService;
import com.wt.admin.service.language.ClassificationService;
import com.wt.admin.service.vector.Vector;
import com.wt.admin.util.AssertUtil;
import com.wt.admin.util.FileUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Service("chatProxy")
@Slf4j
public class ChatProxyServiceImpl implements ChatProxyService, UploadFileService {

    @Autowired
    private Vector vectorStore;
    @Resource
    private ChatModelService chatModelService;
    @Resource
    private ChatModelFileService chatModelFileService;
    @Resource
    private ChatModelContentService chatModelContentService;
    @Resource
    private ClassificationService classificationService;
    @Resource
    InMemoryChatMemory chatMemory;
    @Resource
    ChatClient chatClient;





    @Override
    public ChatModelService getChatModelService() {
        return chatModelService;
    }
    @Override
    public ChatModelFileService getChatModelFileService() {
        return chatModelFileService;
    }
    @Override
    public ChatModelContentService getChatModelContentService() {
        return chatModelContentService;
    }
    @Override
    public ChatClient.ChatClientRequestSpec question(ChatDTO dto, UserVO user) {
        SearchRequest build = SearchRequest.builder().query(dto.getMessage())
                // 指定要返回的相似文档的最大数量
                .topK(5)
                // 介于 0 到 1 之间的双精度值，其中值越接近 1 表示相似度越高
                .similarityThreshold(0.5)
                .build();
        List<Document> documents = vectorStore.getVectorStore().similaritySearch(build);
        documents.forEach(document -> {
            System.out.println(document.getFormattedContent());
        });
        ChatModelEntity byId = chatModelService.findById(dto.getModelId());
        return chatClient
                .prompt("参考向量库中的对话，和用户愉快闲聊")
                .system(sp -> sp.param("name", byId.getChatName()).param("desc", byId.getChatDesc()))
                .advisors(
                        new MessageChatMemoryAdvisor(chatMemory,dto.getContentId().toString(),100),
                        new QuestionAnswerAdvisor(vectorStore.getVectorStore(),build)
                ).user(dto.getMessage());
    }

    @Transactional
    @Override
    public List<ChatModelVO> modeDel(ChatModelDTO data) {
        AssertUtil.objIsNull(data.getId(), BasicCode.BASIC_CODE_99999);
        chatModelFileService.delByModelId(data);
        chatModelContentService.delByModelId(data);
        chatModelService.delById(data);
        // TODO 删除上下文
        vectorStore.deleteByModelId(data.getId());
        return null;
    }

    @Override
    public ChatModeListVO modeList(ChatModelDTO data) {
        ChatModeListVO vo= new ChatModeListVO();
        List<ChatModelVO> chatModelVOS = chatModelService.modeList(data);
        List<ClassificationVO> list = classificationService.list(null);
        vo.setClasss(list);
        vo.setModelList(chatModelVOS);
        return vo;
    }

    @Transactional
    @Override
    public ChatModelFileVO modeFileDel(List<String> data) {
        AssertUtil.List.isEmpty(data, BasicCode.BASIC_CODE_99999);
        // TODO 删除向量库
        chatModelFileService.modeFileDel(data);
        vectorStore.deleteByFileId(data);
        return null;
    }


    @Override
    public void init() {
        log.debug("内存向量 初始化");
        chatModelFileService.listFile().forEach(file -> vectorStore.add(FileUtil.file(FileUtils.getImageAbsURL(file.getUrl())), file.getModelId(), file.getUrl()));
        log.debug("内存向量 初始化结束");
    }

    @Override
    public ChatModelContentVO modeContentDel(ChatModelContentDTO data) {
        ChatModelContentVO chatModelContentVO = chatModelContentService.modeContentDel(data);
        chatMemory.clear(data.getId().toString());
        return chatModelContentVO;
    }

    @Override
    public ChatModelContentVO modeContentEdit(ChatDTO data, UserVO user) {
        ChatModelContentVO chatModelContentVO = chatModelContentService.modeContentEdit(data, user);
        // 根据model_id查询
//        chatMemory.add(chatModelContentVO.getId().toString(),new UserMessage(data.getMessage()));
        return chatModelContentVO;
    }

    @Override
    public ChatModelContentVO modeContentInfo(ChatModelContentDTO data, UserVO user) {
        ChatModelContentVO chatModelContentVO = chatModelContentService.modeContentInfo(data, user);
        // 根据model_id查询
//        ChatModelEntity byId = chatModelService.findById(data.getModelId());
        chatMemory.clear(chatModelContentVO.getId().toString());
        List<Message> list = chatModelContentVO.getContent().stream().map(i -> BeanUtil.copyProperties(i, ChatModelContentEntity.Contents.class))
                .map(ChatModelContentEntity.Contents::toMessage).toList();
        chatMemory.add(chatModelContentVO.getId().toString(), list);
        return chatModelContentVO;
    }

    @Override
    public void reply(String string, ChatDTO data, UserVO user) {
        chatModelContentService.reply(string, data, user);
        chatMemory.add(data.getContentId().toString(), new SystemMessage(string));
    }

    @Transactional
    @Override
    public boolean exec(String path, MultipartFile file, Map<String, String[]> map, UserVO userVO) {
        String modelId = map.get("modelId")[0];
        ChatModelEntity chatModelEntity = chatModelService.findById(Integer.valueOf(modelId));
        ChatModelFileEntity chatModelFileEntity = new ChatModelFileEntity();
        chatModelFileEntity.setUrl(path);
        chatModelFileEntity.setModelId(chatModelEntity.getId());
        chatModelFileEntity.setName(file.getOriginalFilename());
        ChatModelFileEntity chatModelFile = chatModelFileService.saveOne(chatModelFileEntity);
        vectorStore.add(FileUtil.file(FileUtils.getImageAbsURL(path)),Integer.valueOf(modelId),chatModelFile.getUrl());
        return true;
    }

    @Transactional
    @Override
    public boolean batchExec(Map<String,MultipartFile> pathMap, Map<String, String[]> map, UserVO userVO) {
        String modelId = map.get("modelId")[0];
        ChatModelEntity chatModelEntity = chatModelService.findById(Integer.valueOf(modelId));
        List<String>  absPaths = new ArrayList<>(pathMap.size());
        List<ChatModelFileEntity> list = pathMap.keySet().stream().map(i -> {
            ChatModelFileEntity chatModelFileEntity = new ChatModelFileEntity();
            chatModelFileEntity.setUrl(i);
            chatModelFileEntity.setModelId(chatModelEntity.getId());
            chatModelFileEntity.setName(pathMap.get(i).getOriginalFilename());
            absPaths.add(FileUtils.getImageAbsURL(i));
            return chatModelFileEntity;
        }).toList();
        chatModelFileService.batchSave(list);
        absPaths.forEach(i -> vectorStore.add(FileUtil.file(FileUtils.getImageAbsURL(i)), Integer.valueOf(modelId), i));
        return true;
    }


}
